Note: this is a fork of lucacasonato/acme2 that adds External Account Binding
support, needed for ZeroSSL and Google Certificate Manager support. It is packaged separately so that we can use it from other codebases until this upstream PR
is merged.
acme2
A Tokio and
OpenSSL based
ACMEv2 client.
Features:
- ACME v2 support, tested against Let's Encrypt and Pebble
- Fully async, using
reqwest
/ Tokio
- Support for DNS01 and HTTP01 validation
- Fully instrumented with
tracing
Example
This example demonstrates how to provision a certificate for the domain
example.com
using http-01
validation.
use acme2::gen_rsa_private_key;
use acme2::AccountBuilder;
use acme2::AuthorizationStatus;
use acme2::ChallengeStatus;
use acme2::DirectoryBuilder;
use acme2::Error;
use acme2::OrderBuilder;
use acme2::OrderStatus;
use acme2::Csr;
use std::time::Duration;
const LETS_ENCRYPT_URL: &'static str =
"https://acme-v02.api.letsencrypt.org/directory";
#[tokio::main]
async fn main() -> Result<(), Error> {
let dir = DirectoryBuilder::new(LETS_ENCRYPT_URL.to_string())
.build()
.await?;
let mut builder = AccountBuilder::new(dir.clone());
builder.contact(vec!["mailto:hello@lcas.dev".to_string()]);
builder.terms_of_service_agreed(true);
let account = builder.build().await?;
let mut builder = OrderBuilder::new(account);
builder.add_dns_identifier("example.com".to_string());
let order = builder.build().await?;
let authorizations = order.authorizations().await?;
for auth in authorizations {
let challenge = auth.get_challenge("http-01").unwrap();
let challenge = challenge.validate().await?;
let challenge = challenge.wait_done(Duration::from_secs(5), 3).await?;
assert_eq!(challenge.status, ChallengeStatus::Valid);
let authorization = auth.wait_done(Duration::from_secs(5), 3).await?;
assert_eq!(authorization.status, AuthorizationStatus::Valid)
}
let order = order.wait_ready(Duration::from_secs(5), 3).await?;
assert_eq!(order.status, OrderStatus::Ready);
let pkey = gen_rsa_private_key(4096)?;
let order = order.finalize(Csr::Automatic(pkey)).await?;
let order = order.wait_done(Duration::from_secs(5), 3).await?;
assert_eq!(order.status, OrderStatus::Valid);
let cert = order.certificate().await?.unwrap();
assert!(cert.len() > 1);
Ok(())
}
Development
To run the tests, you will need a running Docker instance. Then, run:
cargo test
Licence
This project is licenced under MIT. See LICENCE file for more.